package com.cppsu.cgx.libraryseatselection.services.impl;

import com.cppsu.cgx.libraryseatselection.dao.SeatSelectionDao;
import com.cppsu.cgx.libraryseatselection.dto.SeatSelectionDetails;
import com.cppsu.cgx.libraryseatselection.dto.SeatSelectionDetailsParam;
import com.cppsu.cgx.libraryseatselection.dto.SeatSelectionParam;
import com.cppsu.cgx.libraryseatselection.entity.Seat;
import com.cppsu.cgx.libraryseatselection.entity.SeatSelection;
import com.cppsu.cgx.libraryseatselection.entity.User;
import com.cppsu.cgx.libraryseatselection.exception.ApiException;
import com.cppsu.cgx.libraryseatselection.mapper.*;
import com.cppsu.cgx.libraryseatselection.services.SeatSelectionService;
import com.cppsu.cgx.libraryseatselection.services.UserService;
import org.mybatis.dynamic.sql.SqlBuilder;
import org.mybatis.dynamic.sql.render.RenderingStrategies;
import org.mybatis.dynamic.sql.select.render.SelectStatementProvider;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import static org.mybatis.dynamic.sql.SqlBuilder.*;

/**
 * @Author: cgx
 * @Description:
 * @Date: Created in 15:21 2021/3/10
 * @Modified By:
 */
@Service
public class SeatSelectionServiceImpl implements SeatSelectionService {
    @Autowired
    SeatSelectionMapper seatSelectionMapper;
    @Autowired
    SeatMapper seatMapper;
    @Autowired
    UserService userService;
    @Autowired
    SeatSelectionDao seatSelectionDao;

    @Override
    public List<SeatSelection> list(SeatSelectionParam seatSelectionParam) {
        return seatSelectionMapper.select(c->c
                .where(SeatSelectionDynamicSqlSupport.id,isEqualToWhenPresent(seatSelectionParam.getId()))
                .and(SeatSelectionDynamicSqlSupport.deleteStatus,isEqualTo(0))
                .and(SeatSelectionDynamicSqlSupport.seatId,isLikeWhenPresent(seatSelectionParam.getSeatId()))
                .and(SeatSelectionDynamicSqlSupport.userId,isLikeWhenPresent(seatSelectionParam.getUserId()))
                .and(SeatSelectionDynamicSqlSupport.start,isBetweenWhenPresent(seatSelectionParam.getStart())
                                .and(seatSelectionParam.getEnd())
                        ,or(SeatSelectionDynamicSqlSupport.end,isBetweenWhenPresent(seatSelectionParam.getStart())
                                .and(seatSelectionParam.getEnd())))
        );
    }

    @Override
    public int add(SeatSelectionParam seatSelectionParam) {
        if(seatSelectionParam.getUserId()==null){
            User user = userService.getCurrentUser();
            seatSelectionParam.setUserId(user.getId());
        }
        List<SeatSelection> seatSelectionList = seatSelectionMapper.select(c->c
                .where(SeatSelectionDynamicSqlSupport.seatId,isEqualTo(seatSelectionParam.getSeatId()))
                .and(SeatSelectionDynamicSqlSupport.start, isBetween(seatSelectionParam.getStart()).and(seatSelectionParam.getEnd())
                        ,or(SeatSelectionDynamicSqlSupport.end,isBetween(seatSelectionParam.getStart()).and(seatSelectionParam.getEnd())))
        );
        if(!seatSelectionList.isEmpty()){
            throw new ApiException("该座位在这时间段内已经被选");
        }
        seatSelectionList = seatSelectionMapper.select(c->c.where(SeatSelectionDynamicSqlSupport.userId,isEqualTo(seatSelectionParam.getUserId()))
                .and(SeatSelectionDynamicSqlSupport.start,
                        isBetween(seatSelectionParam.getStart()).and(seatSelectionParam.getEnd()),
                        or(SeatSelectionDynamicSqlSupport.end,isBetween(seatSelectionParam.getStart())
                                .and(seatSelectionParam.getEnd())))
        );
        if(!seatSelectionList.isEmpty()){
            throw new ApiException("您在此时间段内已经有选座，不可再选");
        }
        SeatSelection seatSelection = new SeatSelection();
        BeanUtils.copyProperties(seatSelectionParam,seatSelection);
        seatSelection.setDeleteStatus(0);
        return seatSelectionMapper.insert(seatSelection);
    }

    @Override
    public int update(SeatSelectionParam seatSelectionParam) {
        SeatSelection seatSelection = new SeatSelection();
        BeanUtils.copyProperties(seatSelectionParam,seatSelection);
        return seatSelectionMapper.updateByPrimaryKeySelective(seatSelection);
    }

    @Override
    public int delete(List<Long> ids) {
        return seatSelectionMapper.update(c->c.set(SeatSelectionDynamicSqlSupport.deleteStatus).equalTo(1)
                .where(SeatSelectionDynamicSqlSupport.id,isIn(ids))
        );
    }

    @Transactional
    @Override
    public int returnSeat(List<Long> ids) {
        List<SeatSelection> seatSelectionList = seatSelectionMapper.select(c->c.where(SeatSelectionDynamicSqlSupport.id,isIn(ids)));
        List<Long> seatIdList = seatSelectionList.stream().map(SeatSelection::getSeatId).collect(Collectors.toList());
        seatMapper.update(c->c.set(SeatDynamicSqlSupport.status).equalTo(1).where(SeatDynamicSqlSupport.id,isIn((seatIdList))));
        return seatSelectionMapper.update(c->c.set(SeatSelectionDynamicSqlSupport.returnStatus)
                .equalTo(1)
                .set(SeatSelectionDynamicSqlSupport.end).equalTo(new Date())
                .where(SeatSelectionDynamicSqlSupport.id,isIn(ids))
        );
    }

    @Override
    public List<SeatSelectionDetails> listSeatSelectionDetails(SeatSelectionDetailsParam seatSelectionDetailsParam) {
        if(seatSelectionDetailsParam.getUserId()==null){
            seatSelectionDetailsParam.setUserId(userService.getCurrentUser().getId());
        }
        SelectStatementProvider selectStatement = SqlBuilder.select(
                SeatSelectionDynamicSqlSupport.id.as("id"),
                SeatSelectionDynamicSqlSupport.start.as("start"),
                SeatSelectionDynamicSqlSupport.end.as("end"),
                SeatDynamicSqlSupport.number.as("number"),
                LibraryDynamicSqlSupport.name.as("library_name"),
                FloorDynamicSqlSupport.floorNumber.as("floor_number")
                ).from(SeatSelectionDynamicSqlSupport.seatSelection)
                .leftJoin(SeatDynamicSqlSupport.seat)
                .on(SeatSelectionDynamicSqlSupport.seatId,equalTo(SeatDynamicSqlSupport.id))
                .leftJoin(FloorDynamicSqlSupport.floor)
                .on(SeatDynamicSqlSupport.floorId,equalTo(FloorDynamicSqlSupport.id))
                .leftJoin(LibraryDynamicSqlSupport.library)
                .on(FloorDynamicSqlSupport.libraryId,equalTo(LibraryDynamicSqlSupport.id))
                .where(SeatSelectionDynamicSqlSupport.deleteStatus,isEqualTo(0))
                .and(SeatSelectionDynamicSqlSupport.id,isEqualToWhenPresent(seatSelectionDetailsParam.getSeatSelectionId()),
                        or(SeatSelectionDynamicSqlSupport.userId,isEqualToWhenPresent(seatSelectionDetailsParam.getUserId())))

                .orderBy(SeatSelectionDynamicSqlSupport.start.descending()).build().render(RenderingStrategies.MYBATIS3);
        return seatSelectionDao.listSeatSelectionDetails(selectStatement);
    }

}
